#ifndef GAMEFRAMEWORK_SOUND_H_
#define GAMEFRAMEWORK_SOUND_H_

#include "stdafx.h"
#include "sound_manager.h"

class SoundMp3
{
  /* Enum */
private:
  enum PlayState {
    SOUND_PLAY,
    SOUND_PAUSE,
    SOUND_STOP
  };

  /* struct */
private:
  struct Buffer {
    unsigned char const *start;
    unsigned long length;
    SoundMp3* instance;
  };

  /* Static */

private:

    /* MP3 decode function */

  static mad_flow input(void *data,
      mad_stream *stream);
  
  static mad_flow error(void *data,
      mad_stream *stream,
      mad_frame *frame);
  
  static mad_flow output(void *data,
      const mad_header *header,
      mad_pcm *pcm);

  static signed int scale(mad_fixed_t &sample);

  // For reading info
  static mad_flow outputInfo(void *data,
      const mad_header *header,
      mad_pcm *pcm);
  
  void InitBuffer();

  mad_flow outputInfoInstance(void *data,
      const mad_header *header,
      mad_pcm *pcm);

public:
  static int WINAPI DecodeCallback(void* pInstance);

  /* Constructor, destructor */

public:
  SoundMp3(void);
  SoundMp3(LPWSTR fileName, SoundManager *manager);
  ~SoundMp3(void);
public:
	void Stream();
	void Play(bool loop);
	void Pause();
	void Stop();
private:
  /* Instance method replace for static */
  mad_flow InstanceOutput (
      void *data,
      const mad_header *header, mad_pcm *pcm);
  void Prepare();
  void WriteBuffer(mad_pcm *pcm);
  void WriteData(LPBYTE lpData, // pointer to input buffer
    DWORD dwOffSet, // offset of directsound buffer begin write
    DWORD dwSoundByte); // size want to write
  int Decode();

  /* member variable */
private:

  LPWSTR fileName;
  LPDIRECTSOUNDBUFFER8 buffer8;
  SoundManager *manager;
  int bufferSize;
  HANDLE threadHandle; // thread handle
  HANDLE fileHandle; // sound file handle
  LPVOID mapPointer;
  unsigned long fileLength;
  
  // Fill buffer control member
  //
  DWORD playPos;
  DWORD writePos;
  DWORD prevPlayPos;
  bool firstFillBuffer;

  // Playback control member
  //
  bool loop;
  enum PlayState playState;
};

#endif // GAMEFRAMEWORK_SOUND_H_
